﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using HslCommunication.Reflection;
using Newtonsoft.Json;

namespace HslCommunication
{
	/// <summary>
	/// 超时操作的类<br />
	/// a class use to indicate the time-out of the connection
	/// </summary>
	/// <remarks>
	/// 本类自动启动一个静态线程来处理
	/// </remarks>
	// Token: 0x02000012 RID: 18
	public class HslTimeOut
	{
		/// <summary>
		/// 实例化一个默认的对象<br />
		/// Instantiate a default object
		/// </summary>
		// Token: 0x060000B1 RID: 177 RVA: 0x00004C1D File Offset: 0x00002E1D
		public HslTimeOut()
		{
			this.UniqueId = Interlocked.Increment(ref HslTimeOut.hslTimeoutId);
			this.StartTime = DateTime.Now;
			this.IsSuccessful = false;
			this.IsTimeout = false;
		}

		/// <summary>
		/// 当前超时对象的唯一ID信息，没实例化一个对象，id信息就会自增1<br />
		/// The unique ID information of the current timeout object. If an object is not instantiated, the id information will increase by 1
		/// </summary>
		// Token: 0x1700003E RID: 62
		// (get) Token: 0x060000B2 RID: 178 RVA: 0x00004C54 File Offset: 0x00002E54
		// (set) Token: 0x060000B3 RID: 179 RVA: 0x00004C5C File Offset: 0x00002E5C
		public long UniqueId { get; private set; }

		/// <summary>
		/// 操作的开始时间<br />
		/// Start time of operation
		/// </summary>
		// Token: 0x1700003F RID: 63
		// (get) Token: 0x060000B4 RID: 180 RVA: 0x00004C65 File Offset: 0x00002E65
		// (set) Token: 0x060000B5 RID: 181 RVA: 0x00004C6D File Offset: 0x00002E6D
		public DateTime StartTime { get; set; }

		/// <summary>
		/// 操作是否成功，当操作完成的时候，需要设置为<c>True</c>，超时检测自动结束。如果一直为<c>False</c>，超时检测到超时，设置<see cref="P:HslCommunication.HslTimeOut.IsTimeout" />为<c>True</c><br />
		/// Whether the operation is successful, when the operation is completed, it needs to be set to <c>True</c>, 
		/// and the timeout detection will automatically end. If it is always <c>False</c>, 
		/// the timeout is detected by the timeout, set <see cref="P:HslCommunication.HslTimeOut.IsTimeout" /> to <c>True</c>
		/// </summary>
		// Token: 0x17000040 RID: 64
		// (get) Token: 0x060000B6 RID: 182 RVA: 0x00004C76 File Offset: 0x00002E76
		// (set) Token: 0x060000B7 RID: 183 RVA: 0x00004C7E File Offset: 0x00002E7E
		public bool IsSuccessful { get; set; }

		/// <summary>
		/// 延时的时间，单位毫秒<br />
		/// Delay time, in milliseconds
		/// </summary>
		// Token: 0x17000041 RID: 65
		// (get) Token: 0x060000B8 RID: 184 RVA: 0x00004C87 File Offset: 0x00002E87
		// (set) Token: 0x060000B9 RID: 185 RVA: 0x00004C8F File Offset: 0x00002E8F
		public int DelayTime { get; set; }

		/// <summary>
		/// 连接超时用的Socket，本超时对象主要针对套接字的连接，接收数据的超时检测，也可以设置为空，用作其他用途的超时检测。<br />
		/// Socket used for connection timeout. This timeout object is mainly for socket connection and timeout detection of received data. 
		/// It can also be set to empty for other purposes.
		/// </summary>
		// Token: 0x17000042 RID: 66
		// (get) Token: 0x060000BA RID: 186 RVA: 0x00004C98 File Offset: 0x00002E98
		// (set) Token: 0x060000BB RID: 187 RVA: 0x00004CA0 File Offset: 0x00002EA0
		[JsonIgnore]
		public Socket WorkSocket { get; set; }

		/// <summary>
		/// 是否发生了超时的操作，当调用方因为异常结束的时候，需要对<see cref="P:HslCommunication.HslTimeOut.IsTimeout" />进行判断，是否因为发送了超时导致的异常<br />
		/// Whether a timeout operation has occurred, when the caller ends abnormally, 
		/// it needs to judge <see cref="P:HslCommunication.HslTimeOut.IsTimeout" />, whether it is an exception caused by a timeout sent
		/// </summary>
		// Token: 0x17000043 RID: 67
		// (get) Token: 0x060000BC RID: 188 RVA: 0x00004CA9 File Offset: 0x00002EA9
		// (set) Token: 0x060000BD RID: 189 RVA: 0x00004CB1 File Offset: 0x00002EB1
		public bool IsTimeout { get; set; }

		/// <summary>
		/// 获取到目前为止所花费的时间<br />
		/// Get the time spent so far
		/// </summary>
		/// <returns>时间信息</returns>
		// Token: 0x060000BE RID: 190 RVA: 0x00004CBA File Offset: 0x00002EBA
		public TimeSpan GetConsumeTime()
		{
			return DateTime.Now - this.StartTime;
		}

		/// <inheritdoc />
		// Token: 0x060000BF RID: 191 RVA: 0x00004CCC File Offset: 0x00002ECC
		public override string ToString()
		{
			return string.Format("HslTimeOut[{0}]", this.DelayTime);
		}

		/// <summary>
		/// 新增一个超时检测的对象，当操作完成的时候，需要自行标记<see cref="T:HslCommunication.HslTimeOut" />对象的<see cref="P:HslCommunication.HslTimeOut.IsSuccessful" />为<c>True</c><br />
		/// Add a new object for timeout detection. When the operation is completed, 
		/// you need to mark the <see cref="P:HslCommunication.HslTimeOut.IsSuccessful" /> of the <see cref="T:HslCommunication.HslTimeOut" /> object as <c>True</c>
		/// </summary>
		/// <param name="timeOut">超时对象</param>
		// Token: 0x060000C0 RID: 192 RVA: 0x00004CE4 File Offset: 0x00002EE4
		public static void HandleTimeOutCheck(HslTimeOut timeOut)
		{
			object obj = HslTimeOut.listLock;
			lock (obj)
			{
				bool flag2 = (DateTime.Now - HslTimeOut.threadActiveTime).TotalSeconds > 60.0;
				if (flag2)
				{
					HslTimeOut.threadActiveTime = DateTime.Now;
					bool flag3 = Interlocked.Increment(ref HslTimeOut.activeDisableCount) >= 2;
					if (flag3)
					{
						HslTimeOut.CreateTimeoutCheckThread();
					}
				}
				HslTimeOut.WaitHandleTimeOut.Add(timeOut);
			}
		}

		/// <summary>
		/// 获取当前检查超时对象的个数<br />
		/// Get the number of current check timeout objects
		/// </summary>
		// Token: 0x17000044 RID: 68
		// (get) Token: 0x060000C1 RID: 193 RVA: 0x00004D80 File Offset: 0x00002F80
		[HslMqttApi(Description = "Get the number of current check timeout objects", HttpMethod = "GET")]
		public static int TimeOutCheckCount
		{
			get
			{
				return HslTimeOut.WaitHandleTimeOut.Count;
			}
		}

		/// <summary>
		/// 获取当前的所有的等待超时检查对象列表，请勿手动更改对象的属性值<br />
		/// Get the current list of all waiting timeout check objects, do not manually change the property value of the object
		/// </summary>
		/// <returns>HslTimeOut数组，请勿手动更改对象的属性值</returns>
		// Token: 0x060000C2 RID: 194 RVA: 0x00004D8C File Offset: 0x00002F8C
		[HslMqttApi(Description = "Get the current list of all waiting timeout check objects, do not manually change the property value of the object", HttpMethod = "GET")]
		public static HslTimeOut[] GetHslTimeOutsSnapShoot()
		{
			object obj = HslTimeOut.listLock;
			HslTimeOut[] result;
			lock (obj)
			{
				result = HslTimeOut.WaitHandleTimeOut.ToArray();
			}
			return result;
		}

		/// <summary>
		/// 新增一个超时检测的对象，需要指定socket，超时时间，返回<see cref="T:HslCommunication.HslTimeOut" />对象，用作标记完成信息<br />
		/// Add a new object for timeout detection, you need to specify the socket, the timeout period, 
		/// and return the <see cref="T:HslCommunication.HslTimeOut" /> object for marking completion information
		/// </summary>
		/// <param name="socket">网络套接字</param>
		/// <param name="timeout">超时时间，单位为毫秒<br />Timeout period, in milliseconds</param>
		// Token: 0x060000C3 RID: 195 RVA: 0x00004DD8 File Offset: 0x00002FD8
		public static HslTimeOut HandleTimeOutCheck(Socket socket, int timeout)
		{
			HslTimeOut hslTimeOut = new HslTimeOut
			{
				DelayTime = timeout,
				IsSuccessful = false,
				StartTime = DateTime.Now,
				WorkSocket = socket
			};
			bool flag = timeout > 0;
			if (flag)
			{
				HslTimeOut.HandleTimeOutCheck(hslTimeOut);
			}
			return hslTimeOut;
		}

		// Token: 0x060000C4 RID: 196 RVA: 0x00004E24 File Offset: 0x00003024
		static HslTimeOut()
		{
			HslTimeOut.CreateTimeoutCheckThread();
		}

		// Token: 0x060000C5 RID: 197 RVA: 0x00004E5C File Offset: 0x0000305C
		private static void CreateTimeoutCheckThread()
		{
			HslTimeOut.threadActiveTime = DateTime.Now;
			Thread thread = HslTimeOut.threadCheckTimeOut;
			if (thread != null)
			{
				thread.Abort();
			}
			HslTimeOut.threadCheckTimeOut = new Thread(new ParameterizedThreadStart(HslTimeOut.CheckTimeOut));
			HslTimeOut.threadCheckTimeOut.IsBackground = true;
			HslTimeOut.threadCheckTimeOut.Priority = ThreadPriority.AboveNormal;
			HslTimeOut.threadCheckTimeOut.Start(Interlocked.Increment(ref HslTimeOut.threadUniqueId));
		}

		/// <summary>
		/// 整个HslCommunication的检测超时的核心方法，由一个单独的线程运行，线程的优先级很高，当前其他所有的超时信息都可以放到这里处理<br />
		/// The core method of detecting the timeout of th e entire HslCommunication is run by a separate thread. 
		/// The priority of the thread is very high. All other timeout information can be processed here.
		/// </summary>
		/// <param name="obj">需要传入线程的id信息</param>
		// Token: 0x060000C6 RID: 198 RVA: 0x00004ED0 File Offset: 0x000030D0
		private static void CheckTimeOut(object obj)
		{
			long num = (long)obj;
			for (;;)
			{
				Thread.Sleep(100);
				bool flag = num != HslTimeOut.threadUniqueId;
				if (flag)
				{
					break;
				}
				HslTimeOut.threadActiveTime = DateTime.Now;
				HslTimeOut.activeDisableCount = 0;
				object obj2 = HslTimeOut.listLock;
				lock (obj2)
				{
					for (int i = HslTimeOut.WaitHandleTimeOut.Count - 1; i >= 0; i--)
					{
						HslTimeOut hslTimeOut = HslTimeOut.WaitHandleTimeOut[i];
						bool isSuccessful = hslTimeOut.IsSuccessful;
						if (isSuccessful)
						{
							HslTimeOut.WaitHandleTimeOut.RemoveAt(i);
						}
						else
						{
							bool flag3 = (DateTime.Now - hslTimeOut.StartTime).TotalMilliseconds > (double)hslTimeOut.DelayTime;
							if (flag3)
							{
								bool flag4 = !hslTimeOut.IsSuccessful;
								if (flag4)
								{
									Socket workSocket = hslTimeOut.WorkSocket;
									if (workSocket != null)
									{
										workSocket.Close();
									}
									hslTimeOut.IsTimeout = true;
								}
								HslTimeOut.WaitHandleTimeOut.RemoveAt(i);
							}
						}
					}
				}
			}
		}

		// Token: 0x0400006D RID: 109
		private static long hslTimeoutId = 0L;

		// Token: 0x0400006E RID: 110
		private static List<HslTimeOut> WaitHandleTimeOut = new List<HslTimeOut>(128);

		// Token: 0x0400006F RID: 111
		private static object listLock = new object();

		// Token: 0x04000070 RID: 112
		private static Thread threadCheckTimeOut;

		// Token: 0x04000071 RID: 113
		private static long threadUniqueId = 0L;

		// Token: 0x04000072 RID: 114
		private static DateTime threadActiveTime;

		// Token: 0x04000073 RID: 115
		private static int activeDisableCount = 0;
	}
}
